#include "app_serial.h"

/**
 * @brief 初始化设备串口,
 * @param device 设备
 * @return 0:成功，-1:失败
 */
int app_serial_init(Device_t *device)
{
    // 先设置为原始模式（不自动解析特殊字符）
    app_serial_setRaw(device);
    // 先设置为非阻塞模式，蓝牙测试成功后再设置为阻塞模式
    app_serial_setBlock(device,0);
    // 设置波特率，初始串口波特率为9600
    app_serial_setBaudRate(device, BR_9600);
    // 设置校验位, 默认无校验
    app_serial_setParity(device, PAR_NONE);
    // 设置停止位
    app_serial_setStopBits(device, STOP_1);

    // 更新设备串口设置
    if (tcflush(device->fd, TCIOFLUSH) != 0)
    {
        log_error("tcflush failed");
        return -1;
    }
    log_debug("串口初始化配置成功");
    return 0;
}

/**
 * @brief 设置设备串口波特率
 * @param device 设备
 * @param baudrate 波特率
 * @return 0:成功，-1:失败
 */
int app_serial_setBaudRate(Device_t *device, Baudrate baudrate)
{
    struct termios ter;
    // 获取当前串口配置
    if (tcgetattr(device->fd, &ter) == -1)
    {
        log_error("获取串口 tcgetattr failed");
        return -1;
    }
    // 设置输入输出波特率
    cfsetispeed(&ter, baudrate);
    // 应用配置，但暂时不生效，需要flush时生效
    if (tcsetattr(device->fd, TCSANOW, &ter) == -1)
    {
        log_error("应用配置 tcsetattr failed");
        return -1;
    }
    return 0;
}

/**
 * @brief 设置设备串口校验位
 * @param device 设备
 * @param parity 校验位
 * @return 0:成功，-1:失败
 */
int app_serial_setParity(Device_t *device, Parity parity)
{
    struct termios ter;
    // 获取当前串口配置
    if (tcgetattr(device->fd, &ter) == -1)
    {
        log_error("获取串口 tcgetattr failed");
        return -1;
    }
    // 设置校验位
    ter.c_cflag &= ~(PARENB | PARODD); // 清除校验位
    ter.c_cflag |= parity;
    // 应用配置，但暂时不生效，需要flush时生效
    if (tcsetattr(device->fd, TCSANOW, &ter) == -1)
    {
        log_error("应用配置 tcsetattr failed");
        return -1;
    }
    return 0;
}

/**
 * @brief 设置设备串口停止位
 * @param device 设备
 * @param stopbits 停止位
 * @return 0:成功，-1:失败
 */
int app_serial_setStopBits(Device_t *device, StopBits stopbits)
{
    struct termios ter;
    // 获取当前串口配置
    if (tcgetattr(device->fd, &ter) == -1)
    {
        log_error("获取串口 tcgetattr failed");
        return -1;
    }
    // 设置停止位
    ter.c_cflag &= ~CSTOPB;  // 清除停止位
    ter.c_cflag |= stopbits; // 设置停止位
}

/**
 * @brief 设置设备串口阻塞模式
 * @param device 设备
 * @param block 0:非阻塞，1:阻塞
 * @return 0:成功，-1:失败
 */
int app_serial_setBlock(Device_t *device, int block)
{
    struct termios ter;
    // 获取当前串口配置
    if (tcgetattr(device->fd, &ter) == -1)
    {
        log_error("获取串口 tcgetattr failed");
        return -1;
    }
    // 设置阻塞模式
    if (block)
    {
        ter.c_cc[VMIN] = 1;  // 设置阻塞模式
        ter.c_cc[VTIME] = 0; // 没读到数据，一直等待
    }
    else
    {
        ter.c_cc[VMIN] = 0;  // 设置非阻塞模式
        ter.c_cc[VTIME] = 2; // 单位为100ms 等待时间为0.2秒
    }
    // 应用配置，但暂时不生效，需要flush时生效
    if (tcsetattr(device->fd, TCSANOW, &ter) == -1)
    {
        log_error("应用配置 tcsetattr failed");
        return -1;
    }
    return 0;
}

/**
 * @brief 设置串口设备为原始模式
 * @param device 设备
 * @return 0:成功，-1:失败
 */
int app_serial_setRaw(Device_t *device)
{
    struct termios ter;
    // 获取当前串口配置
    if (tcgetattr(device->fd, &ter) == -1)
    {
        log_error("获取串口 tcgetattr failed");
        return -1;
    }
    // 设置为原始模式
    cfmakeraw(&ter);
    // 应用配置，但暂时不生效，需要flush时生效
    if (tcsetattr(device->fd, TCSANOW, &ter) == -1)
    {
        log_error("应用配置 tcsetattr failed");
        return -1;
    }
    return 0;
}